#ifndef __CORE_HEADER__
#define __CORE_HEADER__
#include "stc12c5620ad.h"
#include <intrinsics.h>
#include <stdlib.h>
#include "math_hack.h"
#include "binary.h"
#include "WString.h"
#include "HardwareSerial.h"

//              STC12C56XXAD SKDIP-28
//
//                   +----U----+
// (D19) SCL  P2.2  1|         |28 Vcc
// (D20)      P2.3  2|         |27 P2.1  SDA (D18)
// RESET       RST  3|     PWM2|26 P2.0  PWM (D 3)
// (D 0) RX    RxD  4|     AIN7|25 P1.7  SCK (D13) - Built in LED
// (D 1) TX    TxD  5|     AIN6|24 P1.6 MISO (D12)
//           XTAL1  6|     AIN5|23 P1.5 MOSI (D11)
//           XTAL2  7|       SS|22 P1.4   SS (D10)
// (D 2)      P3.2  8|INT0     |21 P1.3 AIN3 (D17)
// (D 4)      P3.3  9|INT1     |20 P1.2 AIN2 (D16)
// (D21) SS   P3.4 10|         |19 P1.1 AIN1 (D15)
// (D 5) PWM  P3.5 11|PWM1     |18 P1.0 AIN0 (D14)
// (D 6) PWM  P2.4 12|PWM3 PWM0|17 P3.7  PWM (D 9)
// (D22)      P2.5 13|         |16 P2.7      (D 8)
//             GND 14|         |15 P2.6      (D 7)
//                   +---------+
//
#define OUTPUT       0
#define INPUT        1
#define INPUT_PULLUP 2

#define LOW 0
#define HIGH 1
#define FALLING 2

#define DIGITAL_0  P3_bit.RxD
#define DIGITAL_1  P3_bit.TxD
#define DIGITAL_2  P3_bit.P32
#define DIGITAL_3  P2_bit.P20
#define DIGITAL_4  P3_bit.P33
#define DIGITAL_5  P3_bit.P35
#define DIGITAL_6  P2_bit.P24
#define DIGITAL_7  P2_bit.P26
#define DIGITAL_8  P2_bit.P27
#define DIGITAL_9  P3_bit.P37
#define DIGITAL_10 P1_bit.P14
#define DIGITAL_11 P1_bit.P15
#define DIGITAL_12 P1_bit.P16
#define DIGITAL_13 P1_bit.P17
#define DIGITAL_14 P1_bit.P10
#define DIGITAL_15 P1_bit.P11
#define DIGITAL_16 P1_bit.P12
#define DIGITAL_17 P1_bit.P13
#define DIGITAL_18 P2_bit.P21
#define DIGITAL_19 P2_bit.P22
#define DIGITAL_20 P2_bit.P23
#define DIGITAL_21 P3_bit.P34
#define DIGITAL_22 P2_bit.P25

#define ANALOG_0 P1_bit.P10
#define ANALOG_1 P1_bit.P11
#define ANALOG_2 P1_bit.P12
#define ANALOG_3 P1_bit.P13
#define ANALOG_4 P1_bit.P14
#define ANALOG_5 P1_bit.P15
#define ANALOG_6 P1_bit.P16
#define ANALOG_7 P1_bit.P17

#define A0 14
#define A1 15
#define A2 16
#define A3 17
#define A4 10
#define A5 11
#define A6 12
#define A7 13

//SPI pins
#define SS   10
#define MOSI 11
#define MISO 12
#define SCK  13

//I2C pins
#define SDA  18
#define SCL  19

//LED pin
#define LED_BUILTIN 13

#define PIN_0 0x01
#define PIN_1 0x02
#define PIN_2 0x04
#define PIN_3 0x08
#define PIN_4 0x10
#define PIN_5 0x20
#define PIN_6 0x40
#define PIN_7 0x80

#define LSBFIRST 0
#define MSBFIRST 1

#define BIN 2
#define OCT 8
#define DEC 10
#define HEX 16

typedef unsigned char byte;
typedef bool boolean;
typedef unsigned short word;

void _init();
//Digital I/O
void pinMode(unsigned char pin, unsigned char mode);       //OK
void digitalWrite(unsigned char pin, unsigned char value); //OK
unsigned char digitalRead(unsigned char pin);              //OK

//Time
void delay(unsigned int ms);                               //Not precise
unsigned long micros();                                    //Mot precise
unsigned long millis();                                    //Not precise
void delayMicroseconds(unsigned int us);                   //Not precise

//Analog I/O
void analogReference(unsigned char pin);                   //Not(Impossible) implemented
unsigned int analogRead(unsigned char pin);                //OK
void analogWrite(unsigned char pin, unsigned char value);  //OK

//Advanced I/O
void tone(unsigned char pin, unsigned int freq);           //Not implemented
void tone(unsigned char pin, unsigned int freq,
          unsigned long duration);                         //Not implemented
void noTone(unsigned char pin);                            //Not implemented
unsigned char shiftIn(unsigned char dataPin, 
                      unsigned char clockPin, 
                      unsigned char bitOrder);             //OK(Port)
void shiftOut(unsigned char dataPin, 
              unsigned char clockPin, 
              unsigned char bitOrder,
              unsigned char val);                          //OK(Port)
unsigned long pulseIn(unsigned char pin, 
                      unsigned char value);                //Not implemented
unsigned long pluseIn(unsigned char pin, 
                      unsigned char value, 
                      unsigned long timeout);              //Not implemented

//External Interrupts
void attachInterrupt(unsigned char interruptNum,
                     void (*userFunc)(void), 
                     unsigned char mode);                  //OK
void detachInterrupt(unsigned char interruptNum);          //OK

//Interrupts
void interrupts();                                         //OK
void noInterrupts();                                       //OK

//Math
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
long map(long x, long in_min, long in_max, long out_min, long out_max); //OK(Port)
float pow(float base, float exp);                          //Not Tested
float sqrt(float x);                                       //Not implemented
float mysqrt(float x);

//Trigonometry
float sin(float rad);                                      //Not implemented
float cos(float rad);                                      //Not implemented
float tan(float rad);                                      //Not implemented

//Random Numbers
void randomSeed(unsigned int seed);                        //OK(Port)
long random(long howbig);                                  //OK(Port)
long random(long howsmall, long howbig);                   //OK(Port)

//Bits and Bytes
#define lowByte(w) ((unsigned char) ((w) & 0xff))
#define highByte(w) ((unsigned char) ((w) >> 8))
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1 << (bit)))
#define bitClear(value, bit) ((value) &= ~(1 << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
#define bit(b) (1 << (b))

#endif